package com.lhweb.springsecurity.security;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;

/**
 * 自定义权限不足的处理方法
 * 跳转向配置的页面
 * 也可以配置如logoin.ftl?error=denied转向登陆页面
 * 提醒用户重新登录获取更高权限
 * @author liuhuan
 *2015年1月14日 上午9:06:40
 */
public class MyAccessDeniedHandler implements AccessDeniedHandler{
	
    protected static final Log logger = LogFactory.getLog(AccessDeniedHandlerImpl.class);

    private String errorPage;

    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)
            throws IOException, ServletException {
    	/**
    	 * 对于Ajax请求登陆系统，当会话终止时，对Ajax请求的也需要拒绝访问
    	 */
    	if("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))){	//请求为异步的Ajax请求
    		response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);//登录失效，session超时错误码
    	}else if (!response.isCommitted()) {
            if (errorPage != null) {
                request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException);
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage);
                dispatcher.forward(request, response);
            } else {
                response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
            }
        }
    }

    /**
     * The error page to use. Must begin with a "/" and is interpreted relative to the current context root.
     *
     * @param errorPage the dispatcher path to display
     *
     * @throws IllegalArgumentException if the argument doesn't comply with the above limitations
     */
    public void setErrorPage(String errorPage) {
        if ((errorPage != null) && !errorPage.startsWith("/")) {
            throw new IllegalArgumentException("errorPage must begin with '/'");
        }
        this.errorPage = errorPage;
    }

}
